#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <set>
#include <sys/epoll.h>
#include <unistd.h>
#include "Log.hpp"

namespace EpollerModule
{
    const static int defaultepfd = -1;//epoll句柄
    const static int size = 128;

    class Epoller
    {
    public:
        Epoller():_epfd(defaultepfd){}
        void InitEpoller(){
            _epfd = epoll_create(size);
            if(_epfd == defaultepfd){
                lg.LogMessage(Fatal, "create epfd error~  %s : %d\n", strerror(errno), errno);
                exit(4);
            }
            lg.LogMessage(Info, "create epfd success~ epfd: %d \n", _epfd);
        }
        void AddEvent(int sockfd, uint32_t events){
            fd_list.insert(sockfd);//红黑树的节点，待响应
            epoll_event ev;
            ev.data.fd = sockfd;
            ev.events = events;// ??, 不是给内核的, 给用户的

            int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
            if(n < 0){
                lg.LogMessage(Error, "epoll_ctl Add error, %s : %d", strerror(errno), errno);
            }
        }
        void DelEvent(int sockfd){
            fd_list.erase(sockfd);
            int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, NULL);
            if(n < 0){
                lg.LogMessage(Error, "epoll_ctl Del error, %s : %d", strerror(errno), errno);
            }
        }
        void DebugFdList()
        {
            std::cout << "fd list is : ";
            for(auto &fd : fd_list)
            {
                std::cout << fd << " ";
            }
            std::cout << std::endl;
        }
        int Wait(epoll_event * revs, int maxevents, int timeout){
            int n = ::epoll_wait(_epfd, revs, maxevents, timeout);
            return n;
        }
        ~Epoller()
        {
            if(_epfd >= 0){
                close(_epfd);
            }
            lg.LogMessage(Info, "epoll close success\n");
        }
    private:
        int _epfd;
        std::set<int> fd_list;
    };
}